package com.magnusart.scrumppm.model;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

/**
 * Utility class that tests equality contract
 * @author Magnus Andersson
 *
 * @param <T>
 */
public abstract class BaseSpecification<T extends Comparable<? super T>> 
{
	BaseSpecification(){/* Nothing */}
	T x, y, z, a;
	 
	@Test
	public void equalsContract() throws Exception {
		// Reflexive: For non-null x, x.equals( x ) returns true.
		assertTrue( x.equals( x ) );
		// Symmetric: For non-null x and y, x.equals( y ) return true, 
		// if and only if y.equals( x ) returns true. 
		assertTrue( x.equals( y ) );
		assertTrue( y.equals( x ) );
		
		// Transitive: For non-null x,y,z, if x.equals( y ) returns true and y.equals( z ) returns true,
		// then x.equals( z ) returns true.
		assertTrue( y.equals( z ) );
		assertTrue( x.equals( z ) );
		
		// For non-null x, x.equals( null ) returns false.
		assertFalse( x.equals( null ) );
		
		// Consistent:
		assertFalse( x.equals( a ) );
		assertFalse( y.equals( a ) );
		assertFalse( a.equals( x ) );
		assertFalse( a.equals( y ) );
	}
	
	@Test
	public void hashContract() throws Exception {
		assertTrue( x.hashCode() == y.hashCode() );
		assertTrue( y.hashCode() == x.hashCode() );
		assertTrue( z.hashCode() == z.hashCode() );
		assertTrue( z.hashCode() == x.hashCode() );
		
		int cacheHash = x.hashCode();
		assertTrue( cacheHash == x.hashCode() );
	}

	@Test
	public void comparsionContract() {
		assertTrue( x.compareTo( y ) == 0 ); // x and y are the same!
		assertFalse( x.compareTo( a ) == 0 ); // x and a are not the same!
		assertTrue( x.compareTo( a ) == -( a.compareTo( x ) ) );
	}
}
